<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    const isComplexDataType = (obj) =>
      (typeof obj === 'object' || typeof obj === 'function') && obj !== null;
    const deepClone = function (obj, hash = new WeakMap()) {
      if (obj.constructor === Date) {
        return new Date(obj); //日期对象直接返回一个新的日期对象
      }
      if (obj.constructor === RegExp) return new RegExp(obj); //正则对象直接返回一个新的正则对象

      // 如果循环引用了就用WeakMap来解决
      if (hash.has(obj)) return hash.get(obj);

      let allDesc = Object.getOwnPropertyDescriptors(obj);
      // 遍历传入参数所有键的特性

      let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);

      // 继承原型链
      hash.set(obj, cloneObj);
      for (let key of Reflect.ownKeys(obj)) {
        cloneObj[key] =
          isComplexDataType(obj[key]) && typeof obj[key] !== 'function'
            ? deepClone(obj[key], hash)
            : obj[key];
      }
      return cloneObj;
    };
  </script>
</html>
